package mBio;

import java.io.*;
import java.util.*;
import rfBio.*;
import java.math.*;


public class merge_hits {

	public static void main(String[] args) 
						throws IOException, FileNotFoundException {
		// local variables
		blastm8 ref = new blastm8();
		blastm8 tempblast = new blastm8();
		Vector blastm8Vector = new Vector(100, 100);
		boolean addFlag = true;
		String o_filename = new String();
		int overlap = Type.toInt(args[1]);
		
		// ***************************************************
		// read file section
		// ***************************************************
		
		// open ref_file
		BufferedReader refFile = new BufferedReader ( new FileReader (args[0]));
		
		// read ref_file line by line
		while (true){
			addFlag = true; // asume no overlap and the new hit should be added
			String line = refFile.readLine();
			if (line == null)
			{
				break;
			}			
			
			StringTokenizer ltok = new StringTokenizer(line, "\t");
			while ( ltok.hasMoreTokens() ){
				ref.set_query(ltok.nextToken());
				ref.set_subject(ltok.nextToken());
				ref.set_p1(Type.toFloat( ltok.nextToken() ));
				ref.set_allength(Type.toInt( ltok.nextToken() ));
				ref.set_p2(Type.toInt( ltok.nextToken() ));
				ref.set_p3(Type.toInt( ltok.nextToken() ));
				ref.set_qstart(Type.toInt( ltok.nextToken() ));
				ref.set_qstop(Type.toInt( ltok.nextToken() ));
				ref.set_sstart(Type.toInt( ltok.nextToken() ));
				ref.set_sstop(Type.toInt( ltok.nextToken() ));
				ref.set_evalue(Type.toFloat( ltok.nextToken() ));
				ref.set_score(Type.toInt( ltok.nextToken() ));		
			}
			
			// check if same subject already exists in blastm8Vector
			// and if the distance between these and the hit to add
			// is less then the cut_off
			for(int i=0; i < blastm8Vector.size(); i++){
				//System.out.println("here");
				tempblast = (blastm8) blastm8Vector.get(i);
				if( (tempblast.get_subject().equals(ref.get_subject()))){
					
					//if on pluss strand
					if( tempblast.get_sstart() < tempblast.get_sstop()){

						// if the hit to be added is on pluss strand
						if( ref.get_sstart() < ref.get_sstop() ){
							if( (tempblast.get_sstart() <= (ref.get_sstop() + overlap)) && ((tempblast.get_sstart() >= (ref.get_sstart()))) ){
								//merge 
								tempblast.set_sstart(Math.min(ref.get_sstart(), tempblast.get_sstart()));
								addFlag=false;	
								//System.out.println("1");
							}
							if( (tempblast.get_sstop() >= (ref.get_sstart() - overlap)) && (tempblast.get_sstop() <= (ref.get_sstop()))  ){
								//merge
								tempblast.set_sstop((Math.max(tempblast.get_sstop(), ref.get_sstop())));
								addFlag=false;
								//System.out.println("2");
							}		
						}// end if the hit to be added on pluss strand
						
						// if the hit to be added is on minus strand
						if( ref.get_sstart() > ref.get_sstop() ){
							if( (tempblast.get_sstart() <= (ref.get_sstart() + overlap)) && (tempblast.get_sstart() >= (ref.get_sstop())) ){
								//merge
								tempblast.set_sstart(Math.min(ref.get_sstop(), tempblast.get_sstart()));
								addFlag=false;
								//System.out.println("3");
							}
							if( (tempblast.get_sstop() >= (ref.get_sstop() - overlap)) && (tempblast.get_sstop() <= (ref.get_sstart())) ){
								//merge
								tempblast.set_sstop((Math.max(tempblast.get_sstop(), ref.get_sstart())));
								addFlag=false;	
								//System.out.println("4");
							}
						} // end the hit to be added is on minus strand
						
					
					} // end if on pluss strand
					
					//if on minus strand
					if( tempblast.get_sstart() > tempblast.get_sstop()){

						// if the hit to be added is on pluss strand
						if( ref.get_sstart() < ref.get_sstop() ){
							if( (tempblast.get_sstop() >= (ref.get_sstart())) && (tempblast.get_sstop() <= (ref.get_sstop() + overlap)) ){
								//merge 
								tempblast.set_sstart(Math.min(ref.get_sstart(), tempblast.get_sstop()));
								addFlag=false;	
								//System.out.println("5");
							}
							if( (tempblast.get_sstart() >= (ref.get_sstart() - overlap)) && (tempblast.get_sstart() <= (ref.get_sstop()))){
								//merge
								tempblast.set_sstop((Math.max(tempblast.get_sstart(), ref.get_sstart())));
								addFlag=false;
								//System.out.println("6");
							}		
						}// end if the hit to be added on pluss strand
						
						// if the hit to be added is on minus strand
						if( ref.get_sstart() > ref.get_sstop() ){
							if( (tempblast.get_sstop() >= (ref.get_sstop())) && (tempblast.get_sstop() <= (ref.get_sstart() + overlap)) ){
								//merge
								tempblast.set_sstart(Math.min(ref.get_sstop(), tempblast.get_sstop()));
								addFlag=false;
								//System.out.println("7");
							}
							if( (tempblast.get_sstart() >= (ref.get_sstop() - overlap)) && (tempblast.get_sstart() <= (ref.get_sstart()))  ){
								//merge
								tempblast.set_sstop((Math.max(tempblast.get_sstart(), ref.get_sstart())));
								addFlag=false;	
								//System.out.println("8");
							}
						} // end if the hit to be added is on minus strand
							
					} // end if on minus strand
					
				} // end if same subject
				
				// add the hit to blastm8Vector
				
				
				// the hit was not merged
				if(!addFlag){
					// the hit was merged and tempblast contains the new genomic coordinates, so replace the old hit
					blastm8Vector.set(i,tempblast);
				}
				
	            
			}
			if(addFlag){
				blastm8Vector.add(new blastm8(ref));
			}
			
			addFlag = true; // assume the next hit should be added

		}// end read loop


		
		// close ref_ file
		refFile.close();						
				
		//write new blastm8 table
		o_filename = args[2];
		
		PrintWriter o_file = new PrintWriter(new BufferedWriter(new FileWriter(o_filename)));
		
		for(int i =0; i < blastm8Vector.size(); i++)
		{
				o_file.println( blastm8Vector.get(i));
		}
		
		o_file.close();
		
	} // end main

}
